<?php

namespace App\Command\ResumeParsing\Service;

use App\Command\ResumeParsing\Service\Dict;

//翻译字典类
class TranslateHelper {
    private $resumeInfo;
    private $provider;

    private $dictArea;
    private $dictMajor;
    private $dictIndustry;
    private $dictSex;
    private $dictMarried;
    private $dictPolitic;
    private $dictDegree;
    private $dictJobterm;
    public $dictCurrentSituation;
    private $dictEntryTime;
    private $autoFix;

    function __construct($dictProvider = NULL) {
        if (!$dictProvider) {
            $dictProvider = new Dict\DictHelper();
        }
        $this->autoFix = config('app.resume_machine_learning.fix_machinelearning_result');
        $this->dictProvider = $dictProvider;
        $this->refreshDict($dictProvider);
    }

    function __destruct() {
        //print "Destroying " . $this->name . "\n";
    }

    //更新数据字典
    function refreshDict($provider = NULL) {
        if (!$provider) {
            $provider = $this->dictProvider;
        }
        $this->dictArea = $provider->getAreaDict();
        $this->dictMajor = $provider->getMajorDict();
        $this->dictIndustry = $provider->getIndustryDict();
        $this->dictSex = $provider->getSexDict();
        $this->dictMarried = $provider->getMarriedDict();
        $this->dictPolitic = $provider->getPoliticDict();
        $this->dictDegree = $provider->getDegreeDict();
        $this->dictJobterm = $provider->getJobtermDict();
        $this->dictCurrentSituation = $provider->getCurrentSituationDict();
        $this->dictEntryTime = $provider->getEntryTimeDict();
    }

    function translateResume(&$resumeInfo) {

        $this->resumeInfo = &$resumeInfo;
        //var_dump($this->resumeInfo);
        //翻译性别
        $this->translateSex();

        //翻译婚姻
        $this->translateMarried();

        //翻译学历
        $this->translateDegree();

        //翻译行业
        $this->translateIndustry();

        //翻译工作年限
        $this->translateWorkyear();

        //翻译所在城市
        $this->translateWorkArea();

        //翻译户口所在城市
        $this->translateArea();

        //翻译期望工作城市
        $this->translateExpectArea();

        //翻译当前工资
        //$this->translateSalary();

        //翻译期望工资
        //$this->translateExpectSalary();

        //翻译婚姻
        $this->translateMarried();

        //政治面貌
        $this->translatePolitic();

        //翻译专业
        $this->translateMajor();     //待议

        //翻译职能
        $this->translatePosition();  //待议

        //翻译工作经历
        $this->translateWorkInfo();

        //翻译教育经历
        $this->translateEducationInfo();

        //翻译工作类型(全职/兼职)
        $this->translateJobterm();

        //翻译求职状态
        $this->translateCurrentSituation();

        //翻译到岗时间
        $this->translateEntryTime();

        return $this->resumeInfo;
    }

    function translateSex() {
        $resumeInfo = &$this->resumeInfo;
        $tmp = $resumeInfo['sex'];
        if (empty($tmp)) {
            return;
        }
        $resumeInfo['sex_code'] = isset($this->dictSex[$tmp]) ? $this->dictSex[$tmp] : '';
    }

    function translateMarried() {
        //  \\10.100.2.4\www\inc\co\dd\d_marriage.php

        $resumeInfo = &$this->resumeInfo;
        $tmp = $resumeInfo['married'];
        if (empty($tmp)) {
            return;
        }
        if (($result = $this->translateCode($tmp, $this->dictMarried,false, false)) !== '') {
            $resumeInfo['married_code'] = $result;
        } else {
            $resumeInfo['married_code'] = '';
        }
        //$resumeInfo['married_code'] = isset($this->dictMarried[$tmp]) ? $this->dictMarried[$tmp] : '';
    }

    function translatePolitic() {
        //  \\10.100.2.4\www\inc\co\dd\d_marriage.php

        $resumeInfo = &$this->resumeInfo;
        $tmp = $resumeInfo['politic'];
        if (empty($tmp)) {
            return;
        }
        if (($result = $this->translateCode($tmp, $this->dictPolitic,false, false)) !== '') {
            $resumeInfo['politic_code'] = $result;
        } else {
            $resumeInfo['politic_code'] = '';
        }
//        $resumeInfo['politic_code'] = isset($this->dictPolitic[$tmp]) ? $this->dictPolitic[$tmp] : '';
    }

    function translateDegree() {
        $resumeInfo = &$this->resumeInfo;
        $tmp = strtoupper($resumeInfo['degree']);
        if (empty($tmp)) {
            return;
        }
        if (($result = $this->translateCode($tmp, $this->dictDegree,false, false)) !== '') {
            $resumeInfo['degree_code'] = $result;
        } else {
            $resumeInfo['degree_code'] = '';
        }
//        $resumeInfo['degree_code'] = isset($this->dictDegree[$tmp]) ? $this->dictDegree[$tmp] : '';
    }

    //优先使用简历时间减去工作年限计算得到开始工作时间。若无简历时间则用系统时间
    function translateWorkyear() {
        $resumeInfo = &$this->resumeInfo;
        $tmp = strtoupper($resumeInfo['workyear']);
        if (empty($tmp)) {
            return;
        }

        $time = time();
        //逆过程位于 Model/Resume::getResumeInfo()，须保持一致
        if (!empty($resumeInfo['time']) && ($resumeTime = strtotime($resumeInfo['time'])) < $time && ($resumeTime > 0)) {
            $time = $resumeTime;
        }
        //$time = strtotime((date('Y', $time) + 1) . '-01-01');   //范例：当前为2019年9月24日，则1个月~1年工作经历均记为2019年（输出时2019年=1年工作经历，类似虚岁） edit: 此规则已废弃
        $timespan = 0;
        //处理工作经验为 a - b年 的情况
        if (preg_match('/\d\s*?[~\-－～]{1}\s*?\d\s*?年/u',$tmp,$match)) {
            $match[0] = preg_replace('/[~－～]/','-',$match[0]);
            $workYearArr = explode('-',str_replace(' ','',$match[0]));
            $timespan += $workYearArr[0] * 31536000;
            if (date('Y',$time) - date('Y',$time - $timespan) < 50) {
                $resumeInfo['workyear_code'] = date('Y', $time - $timespan);
            }
        }
        else if (preg_match('/^(?:(?<year>\d{1,2})\s*年)?(?:\s*(?<month>[01]?\d)\s*个?月)?(?:\s*以上|\+)?/u', $tmp, $matches)) {
            if (!empty($matches['year']) || !empty($matches['month'])) {
                if (!empty($matches['year'])) $timespan += $matches['year'] * 31536000;
                if (!empty($matches['month'])) $timespan += $matches['month'] * 2592000;
                if (date('Y',$time) - date('Y',$time - $timespan) < 50) {
                    $resumeInfo['workyear_code'] = date('Y', $time - $timespan);
                }
            }
        }
        //处理工作经验为应届毕业生 或 不满一年的情况
        else if (preg_match('/应届|1年|一年/u',$tmp,$match)) {
            $resumeInfo['workyear_code'] = date('Y', $time);
        }

    }

    function translateWorkArea() {
        $this->resumeInfo['workarea_code'] = $this->getArea($this->resumeInfo['workarea'], false);
    }

    function translateArea() {
        $this->resumeInfo['area_code'] = $this->getArea($this->resumeInfo['area'], false);
    }

    function translateExpectArea() {
        $this->resumeInfo['expectarea_code'] = $this->getArea($this->resumeInfo['expectarea']);
    }

    function getArea($text, $getAll = true) {
        $areaArr = array_values(array_filter(preg_split('/\s*[,;，；、|]\s*/u', $text)));
        if (!count($areaArr)) return '';
        if (count($areaArr) == 1) {
            $code1 = $this->getSingleArea($areaArr[0], $precise);
            if ($code1 && $precise) {
                return $code1;
            } else {
                $areaArr = array_filter(preg_split('/\s+/u', $text));
            }
        }
        $codes = array_filter(array_map(function ($area) {
            return $this->getSingleArea($area);
        }, $areaArr));
        if (!empty($codes)) return $getAll ? implode(',', $codes) : (isset($codes[0]) ? $codes[0] : '');
        if (!empty($code1)) return $code1;
        return '';
    }

    private function getSingleArea($text, &$precise = null) {
        $precise = true;
        $text = preg_replace('/\W+/u', '', $text);
        if (empty($text)) return false;

        $text = strtoupper($text);
        if (!empty($this->translateCode($text, $this->dictArea,false, false))) {
            return $this->translateCode($text, $this->dictArea,false, false);
        }

        $tmpText = preg_replace('/市/u', '', $text, 1);
        if (!empty($this->translateCode($tmpText, $this->dictArea,false, false))) {
            return $this->translateCode($tmpText, $this->dictArea,false, false);
        }

        $tmpText2 = preg_replace('/([省市区旗])+$/u', '$1', $tmpText);
        if (!empty($this->translateCode($tmpText2, $this->dictArea,false, false))) {
            return $this->translateCode($tmpText2, $this->dictArea,false, false);
        }

        $precise = false;
        for ($length = mb_strlen($tmpText2) - 1; $length >= 2; $length--) {
            $try = mb_substr($tmpText2, 0, $length);
            if (!empty($this->translateCode($try, $this->dictArea,false, false))) {
                return $this->translateCode($try, $this->dictArea,false, false);
            }
        }
//        if (isset($this->dictArea[$text])) return $this->dictArea[$text];
//
//        $tmpText = preg_replace('/市/u', '', $text, 1);
//        if (isset($this->dictArea[$tmpText])) return $this->dictArea[$tmpText];
//
//        $tmpText2 = preg_replace('/([省市区旗])+$/u', '$1', $tmpText);
//        if (isset($this->dictArea[$tmpText2])) return $this->dictArea[$tmpText2];
//
//        $precise = false;
//        for ($length = mb_strlen($tmpText2) - 1; $length >= 2; $length--) {
//            $try = mb_substr($tmpText2, 0, $length);
//            if (isset($this->dictArea[$try])) return $this->dictArea[$try];
//        }
        return false;
    }

    function translateMajor() {
        $resumeInfo = &$this->resumeInfo;//var_dump($resumeInfo['major']);
        //$resumeInfo['major'] = '计算机科学与技术本科';
        $tmp = strtoupper($resumeInfo['major']);
        if (empty($tmp)) {
            return;
        }
        $tmpClear = preg_replace('/[^\x{4e00}-\x{9fff}A-Za-z1-9]+/u', '', $tmp);
        if (($result = $this->translateCode($tmpClear, $this->dictMajor,false, false)) !== '') {
            $resumeInfo['major_code'] = $result;
        } else {
            $resumeInfo['major_code'] = '';
        }
    }

    function translateIndustry() {
        $this->resumeInfo['industry_code'] = $this->getIndustryCode($this->resumeInfo['industry']);
    }

    function getIndustryCode($text, $getAll = false, $returnArray = false) {
        if (!empty($result = $this->translateCode($text, $this->dictIndustry, $getAll, $returnArray, null))) return $result;
        if (!empty($result = $this->translateCode($text, $this->dictIndustry, $getAll, $returnArray))) return $result;
        return $this->translateCode($text, $this->dictIndustry, $getAll, $returnArray, '/\s*[,;，；、|()（）\s]\s*/us');
    }

    function translateCode($text, &$dict, $getAll = true, $returnArray = false, $delimiter = '/\s*[,;，；、|]\s*/us') {
        $text = trim($text);
        if (empty($delimiter)) {
            $arr = [$text];
        } else {
            $arr = preg_split($delimiter, $text);
        }
        $result = [];
        foreach ($arr as $item) {
            $formattedItem = preg_replace('/[^\x{4e00}-\x{9fff}A-Za-z1-9]+/u', '', strtoupper($item));
            if (isset($dict[$formattedItem])) {
                $result[$item] = $dict[$formattedItem];
                if (!$getAll) break;
            } else if (!isset($dict[$formattedItem]) && $this->autoFix) {//当机器学习解析出现问题导致翻译字段有误时，将字典内容与待翻译文本进行比较，如有重合则进行翻译
                foreach ($dict as $keyName => $keyCode) {
                    if (strstr($formattedItem,strtoupper($keyName)) != false) {
                        $result[$formattedItem] = $keyCode.'_autofix';
                        break;
                    }
                }
            }
        }
        return $returnArray ? $result : implode(',', $result);
    }

    function translateSalary() {
        $resumeInfo = &$this->resumeInfo;

        $salary = isset($resumeInfo['salaryfrom']) && is_numeric($resumeInfo['salaryfrom']) ? $resumeInfo['salaryfrom'] : (isset($resumeInfo['salaryend']) && is_numeric($resumeInfo['salaryend']) ? $resumeInfo['salaryend'] : -1);
        $resumeInfo['salary_code'] = $this->mapSalaryA($salary);
        $salarym = isset($resumeInfo['salarymfrom']) && is_numeric($resumeInfo['salarymfrom']) ? $resumeInfo['salarymfrom'] : (isset($resumeInfo['salarymend']) && is_numeric($resumeInfo['salarymend']) ? $resumeInfo['salarymend'] : -1);
        $resumeInfo['salarym_code'] = $this->mapSalaryM($salarym);
    }

    //年薪映射
    function mapSalaryA($salary) {
        /*
        1	2万以下
        2	2-3万
        3	3-4万
        4	4-5万
        5	5-6万
        6	6-8万
        7	8-10万
        8	10-15万
        13	15-20万
        9	20-30万
        14	30-40万
        10	40-50万
        15	50-60万
        11	60-80万
        16	80-100万
        12	100万以上
        */
        static $map = array(
            20000 => 1,
            30000 => 2,
            40000 => 3,
            50000 => 4,
            60000 => 5,
            80000 => 6,
            100000 => 7,
            150000 => 8,
            200000 => 13,
            300000 => 9,
            400000 => 14,
            500000 => 10,
            600000 => 15,
            800000 => 11,
            1000000 => 16,
        );
        if (!is_numeric($salary) || $salary <= 0) return '';
        foreach ($map as $upperBound => $code) {
            if ($salary < $upperBound) return $code;
        }
        return 12;
    }

    //月薪映射
    function mapSalaryM($salary) {
        /*
        1	1500以下
        2	1500-1999
        3	2000-2999
        4	3000-4499
        5	4500-5999
        6	6000-7999
        7	8000-9999
        8	10000-14999
        9	15000-19999
        13	20000-24999
        10	25000-29999
        14	30000-39999
        11	40000-49999
        12	50000-69999
        15	70000-99999
        16	100000及以上
        */
        static $map = array(
            1500 => 1,
            2000 => 2,
            3000 => 3,
            4500 => 4,
            6000 => 5,
            8000 => 6,
            10000 => 7,
            15000 => 8,
            20000 => 9,
            25000 => 13,
            30000 => 10,
            40000 => 14,
            50000 => 11,
            70000 => 12,
            100000 => 15,
        );
        if (!is_numeric($salary) || $salary <= 0) return '';
        foreach ($map as $upperBound => $code) {
            if ($salary < $upperBound) return $code;
        }
        return 16;
    }

    function translateExpectSalary() {
        $resumeInfo = &$this->resumeInfo;
        $salary = isset($resumeInfo['expectsalaryend']) && is_numeric($resumeInfo['expectsalaryend']) ? $resumeInfo['expectsalaryend'] : (isset($resumeInfo['expectsalaryfrom']) && is_numeric($resumeInfo['expectsalaryfrom']) ? $resumeInfo['expectsalaryfrom'] : -1);
        $resumeInfo['expectsalary_code'] = $this->mapSalaryA($salary);
        $salarym = isset($resumeInfo['expectsalarymend']) && is_numeric($resumeInfo['expectsalarymend']) ? $resumeInfo['expectsalarymend'] : (isset($resumeInfo['expectsalarymfrom']) && is_numeric($resumeInfo['expectsalarymfrom']) ? $resumeInfo['expectsalarymfrom'] : -1);
        $resumeInfo['expectsalarym_code'] = $this->mapSalaryM($salarym);
    }

    function translatePosition() {
        $resumeInfo = &$this->resumeInfo;
    }

    function translateEducationInfo() {
        if (!is_array($this->resumeInfo['educationinfo'])) return;
        foreach ($this->resumeInfo['educationinfo'] as &$item) {
            if (!empty($item['degree'])) {
                $degree = strtoupper($item['degree']);
                if (($result = $this->translateCode($degree, $this->dictDegree,false, false)) !== '') {
                    $item['degree_code'] = $result;
                } else {
                    $item['degree_code'] = '';
                }
                //$item['degree_code'] = isset($this->dictDegree[$degree]) ? $this->dictDegree[$degree] : '';
            } else {
                $item['degree_code'] = '';
            }
            if (!empty($item['major'])) {
                $major = strtoupper($item['major']);
                if (($result = $this->translateCode($major, $this->dictMajor,false, false)) !== '') {
                    $item['major_code'] = $result;
                } else {
                    $item['major_code'] = '';
                }
            } else {
                $item['major_code'] = '';
            }
        }
    }

    function translateWorkInfo() {
        if (!is_array($this->resumeInfo['workinfo'])) return;
        foreach ($this->resumeInfo['workinfo'] as &$item) {
            if (!empty($item['industry'])) {
                $item['industry_code'] = $this->getIndustryCode($item['industry']);
            } else {
                $item['industry_code'] = '';
            }
        }
    }

    function translateJobterm() {
        $resumeInfo = &$this->resumeInfo;
        $tmp = preg_replace('/[\/\|\\\]/','',$resumeInfo['jobterm']);
        if (empty($tmp)) {
            return;
        }
        if (($result = $this->translateCode($tmp, $this->dictJobterm,false, false)) !== '') {
            $this->resumeInfo['jobterm_code'] = $result;
        } else {
            $this->resumeInfo['jobterm_code'] = '';
        }
        //$resumeInfo['jobterm_code'] = isset($this->dictJobterm[$tmp]) ? $this->dictJobterm[$tmp] : '';
    }

    function translateCurrentSituation() {
        if (empty($tmp = $this->resumeInfo['current_situation'])) return;
        if (($result = $this->translateCode($tmp, $this->dictCurrentSituation,false, false)) !== '') {
            $this->resumeInfo['current_situation_code'] = $result;
        } else {
            $this->resumeInfo['current_situation_code'] = '';
        }
        //$this->resumeInfo['current_situation_code'] = isset($this->dictCurrentSituation[$tmp]) ? $this->dictCurrentSituation[$tmp] : '';
    }

    function translateEntryTime() {
        if (empty($tmp = $this->resumeInfo['entrytime'])) return;
        if (($result = $this->translateCode($tmp, $this->dictEntryTime,false, false)) !== '') {
            $this->resumeInfo['entrytime_code'] = $result;
        } else {
            $this->resumeInfo['entrytime_code'] = '';
        }
        //$this->resumeInfo['entrytime_code'] = isset($this->dictEntryTime[$tmp]) ? $this->dictEntryTime[$tmp] : '';
    }
}